home *** CD-ROM | disk | FTP | other *** search
/ io Programmo 37 / IOPROG_37.ISO / SOFT / Multilizer.exe / disk1 / data1.cab / data1 / [Group9]VCL Source Standard / ivmldfil.pas < prev    next >
Encoding:
Pascal/Delphi Source File  |  1999-08-12  |  21.3 KB  |  920 lines

  1. unit IvMLDFil;
  2.  
  3. {$I IVMULTI.INC}
  4.  
  5. {$A-} { Byte align }
  6.  
  7. interface
  8.  
  9. uses
  10. {$IFDEF WIN32}
  11.   Windows,
  12. {$ELSE}
  13.   WinTypes, WinProcs,
  14. {$ENDIF}
  15.   SysUtils, Classes,
  16.   IvDictio, IvAMulti;
  17.  
  18. const
  19.   MLD_EXTENSION_C = 'mld';
  20.   MLD_TAG_C = 'MLD';
  21.   MLD_VERSION_C = 3;
  22.   CONTEXT_MLD_VERSION_C = 3;
  23.  
  24. type
  25. {$IFNDEF WIN32}
  26.   DWord = Longint;
  27. {$ENDIF}
  28.  
  29.   EIvNotMLDFile = Exception;
  30.  
  31.   TIvMLDHeader = record
  32.     tag: array[0..2] of Char;        { "MLD" }
  33.     version: Byte;                   { version that this MLD uses }
  34.     byteOrder: TIvByteOrder;         { 0 (big endian) or 1 (little endian) }
  35.     characterSet: TIvCharacterSet;   { 0 (Unicode) or 1 (Ansi code page) }
  36.     context: TIvContextCode;         { 0 [], 1 [form+component], 2 [component], or 3 [form]) }
  37.     reserved1: array[0..4] of Byte;  { must be zeros }
  38.     languageCount: Word;
  39.     languageOffset: DWord;
  40.     translationCount: Word;
  41.     translationOffset: DWord;
  42.     localeCount: Word;
  43.     localeOffset: DWord;
  44.     infoSize: Word;
  45.     infoOffset: DWord;
  46.     reserved2: array[0..5] of Byte;  { must be zeros }
  47.   end;
  48.  
  49.   TIvMLDFile = class(TObject)
  50.   protected
  51.     FNativeCodePage: Integer;
  52.     FFreeStream: Boolean;
  53.     FLanguage: TIvLanguage;
  54.     FLocale: TIvLocale;
  55.     FHeader: TIvMLDHeader;
  56.     FStream: TStream;
  57.     FBlockSize: Integer;
  58.  
  59.     function GetLanguageCount: Integer;
  60.     function GetLanguage(index: Integer): TIvLanguage;
  61.  
  62.     function GetLocaleCount: Integer;
  63.     function GetLocale(index: Integer): TIvLocale;
  64.  
  65.     function GetTranslationCount: Integer;
  66.  
  67.     function GetVersion: Integer;
  68.     function GetByteOrder: TIvByteOrder;
  69.     function GetCharacterSet: TIvCharacterSet;
  70.     function GetContextCode: TIvContextCode;
  71.     function GetContextType: TIvContextType;
  72.  
  73.     function ReadByte: Integer;
  74.     function ReadBoolean: Boolean;
  75.     function ReadDWord: Longint;
  76.     function ReadChar(codePage: Integer): Char;
  77.  
  78.     function ReadChars(len, codePage: Integer): String;
  79.     function ReadAnsiChars(len: Integer): String;
  80. {$IFDEF WIN32}
  81.     function ReadWideChars(len: Integer): TIvWideString;
  82. {$ENDIF}
  83.  
  84.     function ReadString(codePage: Integer): String;
  85.  
  86.     procedure SkipBytes(size: Integer);
  87.  
  88.     procedure SetBlockSize;
  89.     procedure MoveToBlockEnd;
  90.  
  91.     procedure ReadHeader;
  92.  
  93.   public
  94.     constructor Create;
  95.     destructor Destroy; override;
  96.  
  97.     procedure GoLanguageSection;
  98.     procedure GoTranslationSection;
  99.     procedure GoLocaleSection;
  100.     procedure GoInfoSection;
  101.  
  102.     function IsOpen: Boolean;
  103.     procedure Open;
  104.     procedure OpenFile(const fileName: String);
  105.     procedure Close;
  106.  
  107.     function GetCurrentLanguage: TIvLanguage;
  108.     function GetCurrentLocale: TIvLocale;
  109.  
  110.     function GetAnsiNative: String;
  111. {$IFDEF IVWIDE}
  112.     function GetWideNative: String;
  113. {$ENDIF}
  114.  
  115.     procedure GetAnsiKey(var str, form, component: String);
  116. {$IFDEF IVWIDE}
  117.     procedure GetWideKey(var str, form, component: WideString);
  118. {$ENDIF}
  119.  
  120.     function GetAnsiString(language, codePage: Integer): String;
  121. {$IFDEF IVWIDE}
  122.     function GetWideString(language, codePage: Integer): WideString;
  123. {$ENDIF}
  124.  
  125.     procedure GetTranslation(
  126.       translation: TIvTranslation;
  127.       language, codePage: Integer);
  128.     procedure GetTranslations(context: TIvContext; list: TStringList);
  129.  
  130.     procedure GetInfo(
  131.       var description, owner: String;
  132.       users: TStrings;
  133.       var time: TDateTime);
  134.     function GetDescription: String;
  135.     function GetOwner: String;
  136.     function GetUsers(users: TStrings): Integer;
  137.  
  138.     function ReadWord: Integer;
  139.     function ReadAnsiString: String;
  140. {$IFDEF WIN32}
  141.     function ReadWideString: TIvWideString;
  142. {$ENDIF}
  143.  
  144.     function UseFormContext: Boolean;
  145.     function UseComponentContext: Boolean;
  146.  
  147.     property NativeCodePage: Integer read FNativeCodePage;
  148.     property Stream: TStream read FStream write FStream;
  149.     property ByteOrder: TIvByteOrder read GetByteOrder;
  150.     property CharacterSet: TIvCharacterSet read GetCharacterSet;
  151.     property ContextCode: TIvContextCode read GetContextCode;
  152.     property ContextType: TIvContextType read GetContextType;
  153.     property Version: Integer read GetVersion;
  154.     property TranslationCount: Integer read GetTranslationCount;
  155.     property LanguageCount: Integer read GetLanguageCount;
  156.     property Languages[i: Integer]: TIvLanguage read GetLanguage;
  157.     property LocaleCount: Integer read GetLocaleCount;
  158.     property Locales[i: Integer]: TIvLocale read GetLocale;
  159.   end;
  160.  
  161.   procedure IvChangeWordByteOrder(var value: Word);
  162.   procedure IvChangeDWordByteOrder(var value: DWord);
  163. {$IFDEF WIN32}
  164.   procedure IvChangeStringByteOrder(var value: TIvWideString);
  165. {$ENDIF}
  166.  
  167. implementation
  168.  
  169. {$IFNDEF WIN32}
  170. const
  171.   CP_ACP = 0;
  172. {$ENDIF}
  173.  
  174. procedure IvChangeWordByteOrder(var value: Word);
  175. begin
  176.   value :=
  177.     ((value and $00FF) shl 8) or
  178.     ((value and $FF00) shr 8);
  179. end;
  180.  
  181. procedure IvChangeDWordByteOrder(var value: DWord);
  182. begin
  183.   value :=
  184.     ((value and $000000FF) shl 24) or
  185.     ((value and $0000FF00) shl 8) or
  186.     ((value and $00FF0000) shr 8) or
  187.     ((value and $FF000000) shr 24);
  188. end;
  189.  
  190. {$IFDEF WIN32}
  191. procedure IvChangeStringByteOrder(var value: TIvWideString);
  192. var
  193.   i: Integer;
  194. begin
  195. {$IFDEF IVWIDE}
  196.   for i := 1 to Length(value) do
  197. {$ELSE}
  198.   for i := 0 to SysStringLen(value) - 1 do
  199. {$ENDIF}
  200.     value[i] := WideChar(((Word(value[i]) and $00FF) shl 8) or ((Word(value[i]) and $FF00) shr 8));
  201. end;
  202. {$ENDIF}
  203.  
  204.  
  205. { TIvMLDFile }
  206.  
  207. constructor TIvMLDFile.Create;
  208. begin
  209.   inherited Create;
  210.   FNativeCodePage := 0;
  211.   FLanguage := TIvLanguage.Create;
  212.   FLocale := TIvLocale.Create;
  213. end;
  214.  
  215. destructor TIvMLDFile.Destroy;
  216. begin
  217.   FLanguage.Free;
  218.   FLocale.Free;
  219.   FStream.Free;
  220.   inherited Destroy;
  221. end;
  222.  
  223. function TIvMLDFile.GetVersion: Integer;
  224. begin
  225.   Result := FHeader.version;
  226. end;
  227.  
  228. function TIvMLDFile.GetByteOrder: TIvByteOrder;
  229. begin
  230.   Result := FHeader.byteOrder;
  231. end;
  232.  
  233. function TIvMLDFile.GetCharacterSet: TIvCharacterSet;
  234. begin
  235.   Result := FHeader.characterSet;
  236. end;
  237.  
  238. function TIvMLDFile.UseFormContext: Boolean;
  239. begin
  240.   Result := (FHeader.context = ivccFull) or (FHeader.context = ivccForm);
  241. end;
  242.  
  243. function TIvMLDFile.UseComponentContext: Boolean;
  244. begin
  245.   Result := (FHeader.context = ivccFull) or (FHeader.context = ivccComponent);
  246. end;
  247.  
  248. function TIvMLDFile.GetContextCode: TIvContextCode;
  249. begin
  250.   Result := FHeader.context;
  251. end;
  252.  
  253. function TIvMLDFile.GetContextType: TIvContextType;
  254. begin
  255.   Result := TIvContext.ContextCodeToType(FHeader.context);
  256. end;
  257.  
  258. function TIvMLDFile.IsOpen: Boolean;
  259. begin
  260.   Result := FStream <> nil;
  261. end;
  262.  
  263. procedure TIvMLDFile.Open;
  264. begin
  265.   ReadHeader;
  266. end;
  267.  
  268. procedure TIvMLDFile.OpenFile(const fileName: String);
  269. begin
  270.   FStream := TFileStream.Create(fileName, fmOpenRead or fmShareDenyNone);
  271.   FFreeStream := True;
  272.   ReadHeader;
  273.   FNativeCodePage := Languages[0].CodePage;
  274.   GoLanguageSection;
  275. end;
  276.  
  277. procedure TIvMLDFile.Close;
  278. begin
  279.   if FFreeStream then
  280.     FStream.Free;
  281.   FStream := nil;
  282. end;
  283.  
  284. procedure TIvMLDFile.SetBlockSize;
  285. begin
  286.   if Version >= 3 then
  287.     FBlockSize := ReadWord - Sizeof(Word);
  288. end;
  289.  
  290. procedure TIvMLDFile.MoveToBlockEnd;
  291. begin
  292.   if (Version >= 3) and (FBlockSize > 0) then
  293.     SkipBytes(FBlockSize);
  294. end;
  295.  
  296. procedure TIvMLDFile.SkipBytes(size: Integer);
  297. begin
  298.   FStream.Seek(size, soFromCurrent);
  299. end;
  300.  
  301. function TIvMLDFile.ReadByte: Integer;
  302. var
  303.   b: Byte;
  304. begin
  305.   FStream.ReadBuffer(b, Sizeof(b));
  306.   Dec(FBlockSize, Sizeof(b));
  307.   Result := b;
  308. end;
  309.  
  310. function TIvMLDFile.ReadBoolean: Boolean;
  311. begin
  312.   Result := Boolean(ReadByte);
  313. end;
  314.  
  315. function TIvMLDFile.ReadWord: Integer;
  316. var
  317.   w: Word;
  318. begin
  319.   FStream.ReadBuffer(w, Sizeof(w));
  320.   Dec(FBlockSize, Sizeof(w));
  321.   if ByteOrder = ivboBigEndian then
  322.     IvChangeWordByteOrder(w);
  323.   Result := w;
  324. end;
  325.  
  326. function TIvMLDFile.ReadDWord: Longint;
  327. var
  328.   dw: DWord;
  329. begin
  330.   FStream.ReadBuffer(dw, Sizeof(dw));
  331.   Dec(FBlockSize, Sizeof(dw));
  332.   if ByteOrder = ivboBigEndian then
  333.     IvChangeDWordByteOrder(dw);
  334.   Result := dw;
  335. end;
  336.  
  337. function TIvMLDFile.ReadChar(codePage: Integer): Char;
  338. begin
  339.   Result := ReadChars(1, codePage)[1];
  340. end;
  341.  
  342. { ReadXXXChars }
  343.  
  344. function TIvMLDFile.ReadChars(len, codePage: Integer): String;
  345. begin
  346. {$IFDEF WIN32}
  347.   SetLength(Result, len);
  348. {$ELSE}
  349.   Result[0] := Chr(len);
  350. {$ENDIF}
  351. {$IFDEF WIN32}
  352.   if CharacterSet = ivcsUnicode then
  353.     Result := IvWStrToStr(ReadWideChars(len), codePage)
  354.   else
  355. {$ENDIF}
  356.     Result := ReadAnsiChars(len);
  357. end;
  358.  
  359. function TIvMLDFile.ReadAnsiChars(len: Integer): String;
  360. begin
  361. {$IFDEF WIN32}
  362.   SetLength(Result, len);
  363. {$ELSE}
  364.   Result[0] := Chr(len);
  365. {$ENDIF}
  366.   if len > 0 then
  367.   begin
  368.     FStream.ReadBuffer(Result[1], len);
  369.     Dec(FBlockSize, len);
  370.   end;
  371. end;
  372.  
  373. {$IFDEF WIN32}
  374. function TIvMLDFile.ReadWideChars(len: Integer): TIvWideString;
  375. begin
  376. {$IFDEF IVWIDE}
  377.   SetLength(Result, len);
  378. {$ELSE}
  379.   Result := SysAllocStringLen(nil, len + 1);
  380. {$ENDIF}
  381.   if len > 0 then
  382.   begin
  383.     FStream.ReadBuffer(Result[1], 2*len);
  384.     Dec(FBlockSize, 2*len);
  385.     if ByteOrder = ivboBigEndian then
  386.       IvChangeStringByteOrder(Result);
  387.   end;
  388. {$IFNDEF IVWIDE}
  389.   Result[len] := Chr(0);
  390. {$ENDIF}
  391. end;
  392. {$ENDIF}
  393.  
  394. { ReadXXXString }
  395.  
  396. function TIvMLDFile.ReadString(codePage: Integer): String;
  397. begin
  398. {$IFDEF WIN32}
  399.   if CharacterSet = ivcsUnicode then
  400.     Result := IvWStrToStr(ReadWideString, codePage)
  401.   else
  402. {$ENDIF}
  403.     Result := ReadAnsiString;
  404. end;
  405.  
  406. function TIvMLDFile.ReadAnsiString: String;
  407. var
  408.   len: Word;
  409. begin
  410.   len := ReadWord;
  411.   Result := ReadAnsiChars(len);
  412. end;
  413.  
  414. {$IFDEF WIN32}
  415. function TIvMLDFile.ReadWideString: TIvWideString;
  416. var
  417.   len: Word;
  418. begin
  419.   len := ReadWord;
  420.   Result := ReadWideChars(len);
  421. end;
  422. {$ENDIF}
  423.  
  424. procedure TIvMLDFile.GoLanguageSection;
  425. begin
  426.   if FHeader.languageOffset = 0 then
  427.     raise Exception.Create('Invalid language offset');
  428.  
  429.   FStream.Seek(FHeader.languageOffset, soFromBeginning);
  430. end;
  431.  
  432. procedure TIvMLDFile.GoTranslationSection;
  433. begin
  434.   if FHeader.translationOffset = 0 then
  435.     raise Exception.Create('Invalid translation offset');
  436.  
  437.   FStream.Seek(FHeader.translationOffset, soFromBeginning);
  438. end;
  439.  
  440. procedure TIvMLDFile.GoLocaleSection;
  441. begin
  442.   if FHeader.localeCount = 0 then
  443.     raise Exception.Create('No custom locales');
  444.   if FHeader.localeOffset = 0 then
  445.     raise Exception.Create('Invalid locale offset');
  446.  
  447.   FStream.Seek(FHeader.localeOffset, soFromBeginning);
  448. end;
  449.  
  450. procedure TIvMLDFile.GoInfoSection;
  451. begin
  452.   if FHeader.infoOffset = 0 then
  453.   begin
  454.     FStream.Seek(0, soFromEnd);
  455.     FHeader.infoOffset := FStream.Position;
  456.   end
  457.   else
  458.     FStream.Seek(FHeader.infoOffset, soFromBeginning);
  459. end;
  460.  
  461. function TIvMLDFile.GetLanguageCount: Integer;
  462. begin
  463.   Result := FHeader.languageCount;
  464. end;
  465.  
  466. function TIvMLDFile.GetLanguage(index: Integer): TIvLanguage;
  467. var
  468.   i: Integer;
  469. begin
  470.   Result := nil;
  471.   GoLanguageSection;
  472.   for i := 0 to index do
  473.     Result := GetCurrentLanguage;
  474. end;
  475.  
  476. function TIvMLDFile.GetLocaleCount: Integer;
  477. begin
  478.   Result := FHeader.localeCount;
  479. end;
  480.  
  481. function TIvMLDFile.GetLocale(index: Integer): TIvLocale;
  482. var
  483.   i: Integer;
  484. begin
  485.   Result := nil;
  486.   GoLocaleSection;
  487.   for i := 0 to index do
  488.     Result := GetCurrentLocale;
  489. end;
  490.  
  491. function TIvMLDFile.GetTranslationCount: Integer;
  492. begin
  493.   Result := FHeader.translationCount;
  494. end;
  495.  
  496. function TIvMLDFile.GetCurrentLanguage: TIvLanguage;
  497. begin
  498.   SetBlockSize;
  499.  
  500.   FLanguage.Primary := ReadWord;
  501.   if Version >= 2 then
  502.     FLanguage.ISOLanguage := ReadChars(2, CP_ACP)
  503.   else
  504.     FLanguage.ISOLanguage := '';
  505.  
  506.   FLanguage.DefaultSub := ReadWord;
  507.   if Version >= 2 then
  508.     FLanguage.ISODefaultCountry := ReadChars(2, CP_ACP)
  509.   else
  510.     FLanguage.ISODefaultCountry := '';
  511.  
  512.   FLanguage.AllSubs := ReadString(CP_ACP);
  513.   if Version >= 2 then
  514.     FLanguage.ISOAllCountries := ReadString(CP_ACP)
  515.   else
  516.     FLanguage.ISOAllCountries := '';
  517.  
  518.   if Version >= 3 then
  519. {$IFDEF WIN32}
  520.     FLanguage.Charset := ReadWord
  521.   else
  522.     FLanguage.Charset := 0;
  523. {$ELSE}
  524.     ReadWord;
  525. {$ENDIF}
  526.  
  527.   FLanguage.CodePage := ReadWord;
  528.   FLanguage.OptionsAsInt := ReadByte;
  529.  
  530.   FLanguage.EnglishName := ReadString(CP_ACP);
  531.   FLanguage.NativeName := ReadString(FLanguage.CodePage);
  532.   FLanguage.FontName := ReadString(CP_ACP);
  533.   FLanguage.FontSize := ReadByte;
  534.  
  535.   MoveToBlockEnd;
  536.  
  537.   FLanguage.Init;
  538.   Result := FLanguage;
  539. end;
  540.  
  541. function TIvMLDFile.GetCurrentLocale: TIvLocale;
  542. var
  543.   i: Integer;
  544. begin
  545.   SetBlockSize;
  546.  
  547.   FLocale.Primary := ReadWord;
  548.   if Version >= 2 then
  549.     FLocale.ISOLanguage := ReadChars(2, CP_ACP)
  550.   else
  551.     FLocale.ISOLanguage := '';
  552.  
  553.   FLocale.Sub := ReadWord;
  554.   if Version >= 2 then
  555.     FLocale.ISOCountry := ReadChars(2, CP_ACP)
  556.   else
  557.     FLocale.ISOCountry := '';
  558.  
  559.   if Version >= 3 then
  560. {$IFDEF WIN32}
  561.     FLocale.Charset := ReadWord
  562.   else
  563.     FLocale.Charset := 0;
  564. {$ELSE}
  565.     ReadWord;
  566. {$ENDIF}
  567.  
  568.   FLocale.CodePage := ReadWord;
  569.   FLocale.IsCustom := ReadBoolean;
  570.  
  571.   FLocale.EnglishLanguageName := ReadString(CP_ACP);
  572.   FLocale.EnglishCountryName := ReadString(CP_ACP);
  573.   FLocale.NativeLanguageName := ReadString(FLocale.CodePage);
  574.   FLocale.NativeCountryName := ReadString(FLocale.CodePage);
  575.   FLocale.Win16LanguageName := ReadString(CP_ACP);
  576.   FLocale.Win16CountryName := ReadString(CP_ACP);
  577.  
  578.   FLocale.MeasurementSystem := TIvMeasurementSystem(ReadByte);
  579.   FLocale.CurrencyString := ReadString(FLocale.CodePage);
  580.   FLocale.CurrencyFormat := TIvCurrencyFormat(ReadByte);
  581.   FLocale.NegCurrFormat := TIvNegativeCurrencyFormat(ReadByte);
  582.   FLocale.CurrencyDecimals := ReadByte;
  583.   FLocale.ThousandSeparator := ReadChar(FLocale.CodePage);
  584.   FLocale.DecimalSeparator := ReadChar(FLocale.CodePage);
  585.  
  586.   FLocale.DateSeparator := ReadChar(FLocale.CodePage);
  587.   FLocale.ShortDateFormat := ReadString(FLocale.CodePage);
  588.   FLocale.LongDateFormat := ReadString(FLocale.CodePage);
  589.  
  590.   FLocale.TimeSeparator := ReadChar(FLocale.CodePage);
  591.   FLocale.TimeAMString := ReadString(FLocale.CodePage);
  592.   FLocale.TimePMString := ReadString(FLocale.CodePage);
  593.   FLocale.TimeLeadingZeros := ReadBoolean;
  594.   FLocale.TimeFormat := TIvTimeFormat(ReadByte);
  595.   FLocale.TimeMarkPosition := TIvTimeMarkPosition(ReadByte);
  596.  
  597.   FLocale.CalendarType := TIvCalendarType(ReadByte);
  598.   FLocale.OptionalCalendarType := TIvCalendarType(ReadByte);
  599.   FLocale.FirstDayOfWeek := TIvDayOfWeek(ReadByte);
  600.   FLocale.FirstWeekOfYear := TIvFirstWeekOfYear(ReadByte);
  601.  
  602.   for i := 1 to 12 do
  603.     FLocale.ShortMonthNames[i] := ReadString(FLocale.CodePage);
  604.   for i := 1 to 12 do
  605.     FLocale.LongMonthNames[i] := ReadString(FLocale.CodePage);
  606.   for i := 1 to 7 do
  607.     FLocale.ShortDayNames[i] := ReadString(FLocale.CodePage);
  608.   for i := 1 to 7 do
  609.     FLocale.LongDayNames[i] := ReadString(FLocale.CodePage);
  610.  
  611.   MoveToBlockEnd;
  612.  
  613.   Result := FLocale;
  614. end;
  615.  
  616. function TIvMLDFile.GetAnsiNative: String;
  617. var
  618.   form, component: String;
  619. begin
  620.   GetAnsiKey(Result, form, component);
  621. end;
  622.  
  623. {$IFDEF IVWIDE}
  624. function TIvMLDFile.GetWideNative: String;
  625. begin
  626. end;
  627. {$ENDIF}
  628.  
  629. procedure TIvMLDFile.GetAnsiKey(var str, form, component: String);
  630. var
  631.   i: Integer;
  632. {$IFDEF IVWIDE}
  633.   wideStr, wideForm, wideComponent: WideString;
  634. {$ENDIF}
  635. begin
  636. {$IFDEF IVWIDE}
  637.   if CharacterSet = ivcsUnicode then
  638.   begin
  639.     GetWideKey(wideStr, wideForm, wideComponent);
  640.     str := IvWStrToStr(wideStr, FNativeCodePage);
  641.     form := IvWStrToStr(wideForm, FNativeCodePage);
  642.     component := IvWStrToStr(wideComponent, FNativeCodePage);
  643.   end
  644.   else
  645. {$ENDIF}
  646.   begin
  647.     str := ReadString(FNativeCodePage);
  648.  
  649.     if UseFormContext then
  650.       form := ReadString(FNativeCodePage)
  651.     else
  652.       form := '';
  653.  
  654.     if UseComponentContext then
  655.       component := ReadString(FNativeCodePage)
  656.     else
  657.       component := '';
  658.  
  659.     for i := 1 to LanguageCount - 1 do
  660.       ReadString(CP_ACP);
  661.   end;
  662. end;
  663.  
  664. {$IFDEF IVWIDE}
  665. procedure TIvMLDFile.GetWideKey(var str, form, component: WideString);
  666. var
  667.   i: Integer;
  668.   ansiStr, ansiForm, ansiComponent: String;
  669. begin
  670.   if CharacterSet = ivcsUnicode then
  671.   begin
  672.     str := ReadWideString;
  673.  
  674.     if UseFormContext then
  675.       form := ReadWideString
  676.     else
  677.       form := '';
  678.  
  679.     if UseComponentContext then
  680.       component := ReadWideString
  681.     else
  682.       component := '';
  683.  
  684.     for i := 1 to LanguageCount - 1 do
  685.       ReadWideString;
  686.   end
  687.   else
  688.   begin
  689.     GetAnsiKey(ansiStr, ansiForm, ansiComponent);
  690.     str := IvStrToWStr(ansiStr, FNativeCodePage);
  691.     form := IvStrToWStr(ansiForm, FNativeCodePage);
  692.     component := IvStrToWStr(ansiComponent, FNativeCodePage);
  693.   end;
  694. end;
  695. {$ENDIF}
  696.  
  697. function TIvMLDFile.GetAnsiString(language, codePage: Integer): String;
  698. var
  699.   i: Integer;
  700. {$IFDEF IVWIDE}
  701.   wide: WideString;
  702. {$ENDIF}
  703. begin
  704. {$IFDEF IVWIDE}
  705.   if CharacterSet = ivcsUnicode then
  706.   begin
  707.     wide := GetWideString(language, codePage);
  708.     Result := IvWStrToStr(wide, codePage);
  709.   end
  710.   else
  711. {$ENDIF}
  712.   begin
  713.     for i := 0 to language - 1 do
  714.     begin
  715.       ReadAnsiString;
  716.       if i = 0 then
  717.       begin
  718.         if UseFormContext then
  719.           ReadAnsiString;
  720.  
  721.         if UseComponentContext then
  722.           ReadAnsiString;
  723.       end;
  724.     end;
  725.     Result := ReadAnsiString;
  726.   end;
  727. end;
  728.  
  729. {$IFDEF IVWIDE}
  730. function TIvMLDFile.GetWideString(language, codePage: Integer): WideString;
  731. var
  732.   i: Integer;
  733.   ansi: String;
  734. begin
  735.   if CharacterSet = ivcsUnicode then
  736.   begin
  737.     for i := 0 to language - 1 do
  738.     begin
  739.       ReadWideString;
  740.       if i = 0 then
  741.       begin
  742.         if UseFormContext then
  743.           ReadWideString;
  744.  
  745.         if UseComponentContext then
  746.           ReadWideString;
  747.       end;
  748.     end;
  749.     Result := ReadWideString;
  750.   end
  751.   else
  752.   begin
  753.     ansi := GetAnsiString(language, codePage);
  754.     Result := IvStrToWStr(ansi, codePage);
  755.   end;
  756. end;
  757. {$ENDIF}
  758.  
  759. procedure TIvMLDFile.GetTranslation(
  760.   translation: TIvTranslation;
  761.   language, codePage: Integer);
  762. var
  763.   i: Integer;
  764. begin
  765.   translation.Str := ReadString(CP_ACP);
  766.  
  767.   if UseFormContext then
  768.     translation.Form := ReadString(CP_ACP)
  769.   else
  770.     translation.Form := '';
  771.  
  772.   if UseComponentContext then
  773.     translation.Component := ReadString(CP_ACP)
  774.   else
  775.     translation.Component := '';
  776.  
  777.   if language = 0 then
  778.     translation.Current := translation.Str
  779.   else
  780.   begin
  781.     for i := 1 to language - 1 do
  782.       ReadString(CP_ACP);
  783.     translation.Current := ReadString(codePage);
  784.   end;
  785.  
  786.   for i := language + 1 to LanguageCount - 1 do
  787.     ReadString(CP_ACP);
  788. end;
  789.  
  790. procedure TIvMLDFile.GetTranslations(context: TIvContext; list: TStringList);
  791. var
  792.   i: Integer;
  793. begin
  794.   context.Clear;
  795.   for i := 0 to FHeader.languageCount - 1 do
  796.   begin
  797.     list.Add(ReadAnsiString);
  798.     if i = 0 then
  799.     begin
  800.       if UseFormContext then
  801.         context.Form := ReadAnsiString;
  802.  
  803.       if UseComponentContext then
  804.         context.Component := ReadAnsiString;
  805.     end;
  806.   end;
  807. end;
  808.  
  809. procedure TIvMLDFile.GetInfo(
  810.   var description, owner: String;
  811.   users: TStrings;
  812.   var time: TDateTime);
  813. var
  814.   i, count: Integer;
  815.   year, month, day, hour, min, sec: Word;
  816.   str: String;
  817. begin
  818.   if Version = 1 then
  819.   begin
  820.     description := '';
  821.     owner := '';
  822.   end
  823.   else if FHeader.infoOffset > 0 then
  824.   begin
  825.     GoInfoSection;
  826.     description := ReadString(CP_ACP);
  827.     owner := ReadString(CP_ACP);
  828.     count := ReadWord;
  829.     for i := 0 to count - 1 do
  830.     begin
  831.       str := ReadString(CP_ACP);
  832.       if users <> nil then
  833.         users.Add(str);
  834.     end;
  835.  
  836.     if Version >= 3 then
  837.     begin
  838.       day := ReadByte;
  839.       month := ReadByte;
  840.       year := ReadWord;
  841.  
  842.       hour := ReadByte;
  843.       min := ReadByte;
  844.       sec := ReadByte;
  845.  
  846.       time := EncodeDate(year, month, day) + EncodeTime(hour, min, sec, 0);
  847.     end;
  848.   end;
  849. end;
  850.  
  851. function TIvMLDFile.GetDescription: String;
  852. begin
  853.   if FHeader.infoOffset > 0 then
  854.   begin
  855.     GoInfoSection;
  856.     Result := ReadString(CP_ACP);
  857.   end
  858.   else
  859.     Result := '';
  860. end;
  861.  
  862. function TIvMLDFile.GetOwner: String;
  863. begin
  864.   if FHeader.infoOffset > 0 then
  865.   begin
  866.     GoInfoSection;
  867.     ReadString(CP_ACP);
  868.     Result := ReadString(CP_ACP);
  869.   end
  870.   else
  871.     Result := '';
  872. end;
  873.  
  874. function TIvMLDFile.GetUsers(users: TStrings): Integer;
  875. var
  876.   i: Integer;
  877. begin
  878.   if FHeader.infoOffset > 0 then
  879.   begin
  880.     GoInfoSection;
  881.     ReadString(CP_ACP);
  882.     ReadString(CP_ACP);
  883.     Result := ReadWord;
  884.     for i := 0 to Result - 1 do
  885.       users.Add(ReadString(CP_ACP));
  886.   end
  887.   else
  888.     Result := 0;    
  889. end;
  890.  
  891. procedure TIvMLDFile.ReadHeader;
  892. begin
  893.   FStream.Seek(0, soFromBeginning);
  894.   FStream.ReadBuffer(FHeader, Sizeof(FHeader));
  895.   if FHeader.tag <> MLD_TAG_C then
  896.     raise EIvNotMLDFile.Create('The stream is not a valid MLD stream');
  897.  
  898.   if FHeader.version = 1 then
  899.   begin
  900.     FHeader.characterSet := TIvCharacterSet(FHeader.reserved1[0]);
  901.     FHeader.reserved1[0] := 0;
  902.     FHeader.infoSize := 0;
  903.     FHeader.infoOffset := 0;
  904.   end;
  905.  
  906.   if FHeader.ByteOrder = ivboBigEndian then
  907.   begin
  908.     IvChangeWordByteOrder(FHeader.languageCount);
  909.     IvChangeDWordByteOrder(FHeader.languageOffset);
  910.     IvChangeWordByteOrder(FHeader.translationCount);
  911.     IvChangeDWordByteOrder(FHeader.translationOffset);
  912.     IvChangeWordByteOrder(FHeader.localeCount);
  913.     IvChangeDWordByteOrder(FHeader.localeOffset);
  914.     IvChangeWordByteOrder(FHeader.infoSize);
  915.     IvChangeDWordByteOrder(FHeader.infoOffset);
  916.   end;
  917. end;
  918.  
  919. end.
  920.